package objects;

import interfaces.ActionInterface;

import interfaces.AgentInterface;
import interfaces.impl.HumanInteraction;

import java.awt.Graphics;
import java.util.ArrayList;

import universe.Universe;
import constants.Constants;

import constants.ObjectType;
import extra.Position;




public class WorldObject implements Comparable<WorldObject> {

	private Position position; //that refers to the mid position, where there are collision with the terrain
	private int type;
	private int ID;
	private int owner= Constants.NO_OWNER;
	
	private ImageObject imageObject;
	private int objectReference; //its His ID  but now i used to refers images
	
	private ArrayList<WorldObject> listObjects;
	private ArrayList<WorldObject> listFather;
	
	
	private	ArrayList<ActionInterface> immediatlyActions;
	
	 
	
	private ArrayList<ActionInterface> listActions;
	private ArrayList<SpetialFeature>  listFeatures;
	private ArrayList<AgentInterface>  listAgents;
	
	private ArrayList<HumanInteraction> listHumanInteractions;
	
	private ArrayList<AgentInterface> listAgentsToRemove;
	
	private double actionWaitTime=0;
	private boolean executing=false;
	
	private boolean visible = true;
	private boolean isActive = true;
	private String real = "REAL";
	private int isBackground = Constants.FALSE;
	
		
	public WorldObject(){
		
		position=new Position();
		objectReference= Constants.NO_OBJECT_REFERENCE;
		imageObject=new ImageObject();//.createImageObject(Constants.OBJECT_REFERENCE_BOMBERMAN);
		setObjectReference(objectReference);
		type=ObjectType.NORMAL;
		
		listFeatures= new ArrayList<SpetialFeature>();
		listAgents = new ArrayList<AgentInterface>();
		listActions= new ArrayList<ActionInterface>();
		
		
		immediatlyActions=new ArrayList<ActionInterface>();
		
		listHumanInteractions= new ArrayList<HumanInteraction>();
		listObjects = new ArrayList<WorldObject>();
		
		listAgentsToRemove= new ArrayList<AgentInterface>();
		listFather = new ArrayList<WorldObject>();
	}
	
	public WorldObject(WorldObject object){
		
		real ="NO REAL";
		
		this.position= new Position(object.position);
		this.type=object.type;
		this.ID=object.ID;
		this.owner=object.owner;
		this.isActive = object.isActive;
		
		this.objectReference=object.objectReference;
		this.setObjectReference(objectReference);
		
		this.imageObject= new ImageObject(object.getImageObject());

		
		this.listAgents= (ArrayList<AgentInterface>) object.listAgents;
		this.listFeatures = (ArrayList<SpetialFeature>) object.listFeatures.clone();
		this.listActions = (ArrayList<ActionInterface>) object.listActions.clone();
		this.listHumanInteractions = (ArrayList<HumanInteraction>) object.listHumanInteractions;
		this.listObjects = (ArrayList<WorldObject>) object.listObjects.clone();
		this.listFather= (ArrayList<WorldObject>) object.listFather.clone();
		this.immediatlyActions = (ArrayList<ActionInterface>) object.immediatlyActions.clone();
		this.listAgentsToRemove = (ArrayList<AgentInterface>) object.listAgentsToRemove.clone();
		
		
		
		
	}

	public int getType() {
		return type;
	}


	public void setType(int type) {
		this.type = type;
	}

	public void paint(Graphics g) {
		
		imageObject.paint(g);
		
	}

	/*public void paintCollitionShape(Graphics g){
		g.setColor(Color.black);
		g.drawRect(x+xRadio,y+yRadio,radioWidth,radioHeight);
		g.fillRect(x+xRadio,y+yRadio,radioWidth,radioHeight);
		
	}*/
		
	@Override
	public int compareTo(WorldObject object) {
		if(position.getY()<object.position.getY()){
			
			return -1;
		}
		if(position.getY()>object.position.getY()){
			return 1;
		}
		return 0;

	}

	public int getObjectReference() {
		return objectReference;
	}
 
	public void setObjectReference(int objectReference) {
		this.objectReference = objectReference;
	}
	
	public void addSpetialFeature(SpetialFeature feature) {
		listFeatures.add(new SpetialFeature(feature));
	}

	public void addAgent(AgentInterface agent){
		listAgents.add(agent);
	}
	
	public void print() {
		for(SpetialFeature feat : listFeatures){
			System.out.println(feat.getName()+" value: "+feat.getValue());
		}
		
	}

	public ArrayList<SpetialFeature> getListFeatures() {
		return listFeatures;
	}

	public void setListFeatures(ArrayList<SpetialFeature> listFeatures) {
		this.listFeatures = listFeatures;
	}

	public ArrayList<AgentInterface> getListAgents() {
		return listAgents;
	}

	public void setListAgents(ArrayList<AgentInterface> listAgents) {
		this.listAgents = listAgents;
	}

	public String save(String save) {
		
		save=save +factory.Constants.OBJECT_WORLD_ID+","+position.getX()+","+position.getY()+","+objectReference;

		for(AgentInterface ag : listAgents ){
			save=save+","+ag.getID();
		}
		
		if(!listFeatures.isEmpty()){
		save = save +",SPETIAL";
			for(SpetialFeature fe : listFeatures){
				//save Features
				save=save+","+fe.save();
			}
		}
		
		if(!listActions.isEmpty()){
			save = save +",ACTIONS";
				for(ActionInterface ac : listActions){
					//save Features
					save=save+","+ac.getId();
				}
			}
		
		
		save=save+System.getProperty("line.separator");
				
		
		return save;
	}
	
	public WorldObject load(String[] linesElements, int i) {
		
		double x,y;
		
		x=Float.parseFloat(linesElements[i]);
		i++;
		y=Float.parseFloat(linesElements[i]);
		i++;
		WorldObject obj = new WorldObject();//ObjectFactory.createWorldObject(Integer.parseInt(linesElements[i]));
		obj.setObjectReference(Integer.parseInt(linesElements[i]));
		obj.position=new Position(x,y);
		
		return obj;
		/*WorldObject obj = new WorldObject();
		obj.position.setX((Float.parseFloat(linesElements[i])));
		i++;
		obj.position.setY(Float.parseFloat(linesElements[i]));
		i++;
		obj.setObjectReference(Integer.parseInt(linesElements[i]));
		
		i++;
		//Load Agents
		for(int j=i;j<linesElements.length;j++){
			if(linesElements[j].equals("SPETIAL")){
				i=j;
				break; 
			}
			else{
				System.out.println("Estoy pegando Agentes "+Integer.parseInt(linesElements[j]));
				AgentSingleton.setAgent(obj, Integer.parseInt(linesElements[j]));
				
				
			}
		}
		//load SpetialFeatures
		if(i<linesElements.length){
			if(linesElements[i].equals("SPETIAL")){
				i++;
				SpetialFeature feature = new SpetialFeature();
				for(int j=i;j<linesElements.length;j++){
					if(linesElements[j].equals("ACTIONS")){
						i=j;
						break;
					}
					feature.setId(Integer.parseInt(linesElements[j]));
					j++;
					feature.setName(linesElements[j]);
					j++;
					feature.setValue(Double.parseDouble(linesElements[j]));
					obj.addSpetialFeature(feature);
				}
			}
			if(linesElements[i].equals("ACTIONS")){
				i++;
				for(int j=i;j<linesElements.length;j++){
					obj.addAction(ActionFactory.getAction(Integer.parseInt(linesElements[j])));
					System.out.println("Cargo Action "+Integer.parseInt(linesElements[j]));
				}
			}
		}
		
		return obj;*/
	}
	
	public boolean containsAgent(int id){
		for(AgentInterface ag : listAgents){
			if (ag.getID()==id){
				return true;
			}
		}
		return false;
	}

	public void removeAgent(int agentReference) {
		for(AgentInterface ag : listAgents){
			if(ag.getID()==agentReference){
				listAgents.remove(ag);
				return;
			}
		}
		
	}
	public boolean containsSpetialFeature(int id){
		for(SpetialFeature fe : listFeatures){
			if (fe.getId()==id){
				return true;
			}
		}
		return false;
	}

	public void removeSpetialFeature(int featureReference) {
		for(SpetialFeature fe : listFeatures){
			if (fe.getId()==featureReference){
				listFeatures.remove(fe);
				return;
			}
		}
		
	}

	public Position getPosition() {
		return position;
	}

	public void setPosition(Position position) {
		this.position = position;
		
		
			int x = (int)(position.getX()-imageObject.getImageToShow().getWidth()/2);
			int y = (int)(position.getY()-imageObject.getImageToShow().getHeight()/2);
			imageObject.setPosition(new Position(x,y));
		
		
	}

	public ImageObject getImageObject() {
		return imageObject;
	}

	public void setImageObject(ImageObject imageObject) {
		this.imageObject = imageObject;
	}

	public ArrayList<ActionInterface> getListActions() {
		return listActions;
	}

	public void setListActions(ArrayList<ActionInterface> listActions) {
		this.listActions = listActions;
	}
	
	

	
	
	public void setImmediatlyActionToDo(ActionInterface action){

		/*for(ActionInterface ac : immediatlyActions){
			if(ac.getId()==action.getId()){
				return;
			}
		}*/
		
		ActionInterface actadd =action.cloneAction();
		
		for(ActionInterface ac : listActions){
			if(ac.getId()==action.getId()){
				
				ac.modifyAction(action);
				//System.out.println("Agregue la accion "+action.getName()+" id:"+action.getId());
				actadd.modifyAction(ac);
				immediatlyActions.add(ac.cloneAction());
				return;
			}
		}
		
				
		
	}
	
	public void addAction(ActionInterface action){
		listActions.add(action);
		
	}
	
	
	
	
	
	
	
	
	public void processImmediatlyActions(Universe universe){
		Object list[] = immediatlyActions.toArray();
		
		for (int i =0;i<list.length;i++){
			ActionInterface action = (ActionInterface) list[i];
			action.processAction(universe);
			
			immediatlyActions.remove(action);
			
		}
		
		
		//immediatlyActions= new ArrayList<ActionInterface>();
		
		
		
	}

	
	
	public ArrayList<ActionInterface> getImmediatlyActions() {
		return immediatlyActions;
	}

	public void setImmediatlyActions(ArrayList<ActionInterface> immediatlyActions) {
		this.immediatlyActions = immediatlyActions;
	}

	public void addHumanInteraction(HumanInteraction humanInteraction) {
		
			listHumanInteractions.add(humanInteraction);
			listAgents.add(humanInteraction);
		
	}

	public ArrayList<HumanInteraction> getListHumanInteractions() {
		return listHumanInteractions;
	}

	public void setListHumanInteractions(ArrayList<HumanInteraction> listHumanInteractions) {
		this.listHumanInteractions = listHumanInteractions;
	}

	public ArrayList<WorldObject> getListObjects() {
		return listObjects;
	}

	public void addObject(WorldObject object) {
		listObjects.add(object);
		object.addFather(this);
	}

	private void addFather(WorldObject object) {
			this.listFather.add(object);
	}

	public boolean isVisible() {
		return visible;
	}

	public void setVisible(boolean visible) {
		this.visible = visible;
	}

	public boolean isActive() {
		// TODO Auto-generated method stub
		return isActive ;
	}

	public boolean isExecuting() {
		return executing;
	}

	public void setExecuting(boolean executing) {
		this.executing = executing;
	}

	public void setActive(boolean isActive) {
		this.isActive = isActive;
	}
	
	public void addAgentToRemove(AgentInterface ag){
		listAgentsToRemove.add(ag);
	}
	
	public void processAgentsToRemove() {
		for(AgentInterface ag : listAgentsToRemove){
			listAgents.remove(ag);
		}
		listAgentsToRemove.clear();
	}

	public ArrayList<WorldObject> getListFather() {
		return listFather;
	}

	public void setListFather(ArrayList<WorldObject> listFather) {
		this.listFather = listFather;
	}

	
	public String messageUpdateObject(){
		String result = new String();
			result=+objectReference+";"+getPosition().getX()+";"+getPosition().getY()+";"+isActive+";"+ID+";"+owner+";"+isBackground;
			for(SpetialFeature feature : listFeatures){
				result=result+";"+feature.getId()+";"+feature.getName()+";"+feature.getValue();
			}
		
		return result;
	}
	
	



	public static Position getPositionFromMessageAskForActionFromObject(String str) {
		Position p= new Position();
		String r[]=str.split(";");
		p.setX(Double.parseDouble(r[0]));
		p.setY(Double.parseDouble(r[1]));
		
		return p;
	}

	public String messageAgentsFromObject(int idCliente) {
		String msg = new String();
		for(HumanInteraction ag : listHumanInteractions){
			if(ag.getPermisology()== Constants.NO_PERMISOLOGY || owner==idCliente){
				msg=msg+ag.getName()+System.getProperty("line.separator");
			}
		}
		return msg;
	}

	public int getID() {
		// TODO Auto-generated method stub
		return ID;
	}

	public void setID(int id) {
		this.ID=id;
		
	}

	public void setOwner(int owner){
		this.owner=owner;
	}
	public int getOwner(){
		return owner;
	}

	public WorldObject getObject(int id) {
		for(WorldObject obj : listObjects){
			if(obj.ID==id){
				return obj;
			}
		}
		return null;
	}

	public SpetialFeature getFeature(int spetialFeatureReference) {
		for(SpetialFeature feature : listFeatures){
			if(feature.getId()==spetialFeatureReference){
				return feature;
			}
		}
		return null;
	}

	public WorldObject getObjectFromList(int objectReference) {
		
		for(WorldObject obj : listObjects){
			if (obj.getObjectReference()==objectReference){
				return obj;
			}
		}
		
		return null;
	}

	public boolean containsObject(WorldObject obj) {
		
		return (listObjects.contains(obj));
	}

	public String getReal() {
		
		return real ;
	}

	public void desactivateAllHumanInteractions() {
		for(HumanInteraction ag : listHumanInteractions){
			ag.setActive(false);
		}
		
	}

	public int getIsBackground() {
		return isBackground;
	}

	public void setIsBackground(int isBackground) {
		this.isBackground = isBackground;
	}

	public void clearImmediatlyActions() {
		immediatlyActions = new ArrayList<ActionInterface>();
		
	}

	
	
}
